<template>
  <div class="custom-transfer-wrap">
    <div class="transfer-left">
      <div class="header-wrap">
        <a-input-search v-model="leftSearchValue"
                        placeholder="请输入搜索内容，回车搜索"
                        style="width: 300px;"
                        @pressEnter="onLeftSearch" />
        <span>组织机构</span>
      </div>
      <div class="body-wrap">
        <a-tree blockNode
                checkable
                checkStrictly
                :checkedKeys="selectedLeftKeys"
                :loadedKeys="loadedKeys"
                :expandedKeys="expandedKeys"
                @check="onSelectTree"
                @expand="onExpand"
                @load="onLoad"
                :load-data="getUnitTreeData"
                :tree-data="unitUserTreeData" />
      </div>
    </div>
    <div class="transfer-operation">
      <a-button type="primary"
                :disabled="leftMove"
                @click="onLeftMove"
                size="small"
                icon="left" />
      <a-button type="primary"
                @click="onRightMove"
                :disabled="rightMove"
                size="small"
                icon="right" />
    </div>
    <div class="transfer-right">
      <div class="header-wrap">
        <a-input-search v-model="rightSearchValue"
                        placeholder="请输入搜索内容"
                        style="width: 300px;" />
        <span>条线范围</span>
      </div>
      <div class="body-wrap">
        <a-table :data-source="computedTableSource"
                 :columns="tableColumns"
                 :row-selection="{ selectedRowKeys: checkedRightKeys, onChange: onSelectChange }"
                 :pagination="false">
          <template slot="showFullTitle"
                    slot-scope="text, record">
            <a-tooltip>
              <template slot="title">
                {{ record.fullUnitName || text }}
              </template>
              {{ text }}
            </a-tooltip>
          </template>
        </a-table>
      </div>
    </div>
  </div>
</template>

<script>
import { unituser } from '../../api/businessline/index'
export default {
  name: 'CustomTransfer',
  props: {
    list: {
      type: Array,
      default: () => []
    }
  },
  data () {
    return {
      leftMove: true,
      rightMove: true,
      leftSearchValue: '',
      rightSearchValue: '',
      unitUserTreeData: [],
      tableSource: [],
      loadedKeys: [],
      expandedKeys: [],
      childDisabledKeys: [],
      selectedLeftKeys: [],
      checkedRightKeys: [],
      checkedLeftKeys: [], // 当前左侧勾选的项
      tableColumns: [
        { title: '名称', dataIndex: 'title', scopedSlots: { customRender: 'showFullTitle' } },
        { title: '类型', dataIndex: 'typeText' }
      ],
      typeConfig: {
        2: '单位',
        3: '部门',
        10: '人员'
      }
    }
  },
  watch: {
    checkedLeftKeys: function (newVal) {
      this.rightMove = newVal.length === 0
    },
    checkedRightKeys: function (newVal) {
      this.leftMove = newVal.length === 0
    },
    tableSource: function (newVal) {
      this.$emit('change', JSON.parse(JSON.stringify(newVal)))
    },
    list: function (newVal) {
      let list = JSON.parse(JSON.stringify(newVal || []))
      list = list.map(item => {
        item.typeText = this.typeConfig[item.type]
        return item
      })
      this.tableSource = list
      this.selectedLeftKeys = this.tableSource.map(item => item.key)
    },
    leftDisableKeys: function () {
      this.setTreeNodeDisable(this.unitUserTreeData)
    }
  },
  computed: {
    leftDisableKeys: function () {
      const tableKeys = this.tableSource.map(item => item.key)
      return [...new Set([...this.childDisabledKeys, ...tableKeys])]
    },
    computedTableSource: function () {
      if (this.rightSearchValue) {
        return this.tableSource.filter(item => {
          return item.title.includes(this.rightSearchValue)
        })
      } else {
        return this.tableSource
      }
    }
  },
  mounted () {
    this.$nextTick(() => {
      this.getUserList()
    })
  },
  methods: {
    async getUserList (search = '') {
      const result = await unituser({ nameall: search })
      this.expandedKeys = []
      this.loadedKeys = []
      this.unitUserTreeData = result.unitusertree
      this.$nextTick(() => {
        this.setTreeNodeDisable(this.unitUserTreeData)
      })
    },
    onExpand (expandedKeys) {
      this.expandedKeys = expandedKeys
    },
    onLoad (loadedKeys) {
      this.loadedKeys = loadedKeys
    },
    onLeftSearch () {
      this.getUserList(this.leftSearchValue)
    },
    onRightMove () {
      let moveList = this.getTreeNodes(this.unitUserTreeData, this.checkedLeftKeys)
      if (moveList.length > 0) {
        moveList = moveList.map(item => {
          const parentNodes = this.getParentNodesByChild(item, 'key')
          const fullUnitName = parentNodes.reduce((res, node) => {
            res += `${node.title}/`
            return res
          }, '')
          const parentIds = parentNodes.reduce((res, node) => {
            res += `${node.key},`
            return res
          }, '')
          return {
            key: item.key,
            title: item.title,
            fullUnitName: `${fullUnitName}${item.title}`,
            typeText: this.typeConfig[item.type],
            parentIds: parentIds,
            type: item.type
          }
        })
        moveList = moveList.filter(item => {
          return !this.leftDisableKeys.includes(item.key)
        })
        this.clearChildNodes(moveList)
        this.tableSource = this.tableSource.concat(moveList)
        this.checkedLeftKeys = []
      }
    },
    // 当子级的父级被选中时，从右侧列表中清除对应的子级
    clearChildNodes (moveList) {
      for (let i = this.tableSource.length - 1; i >= 0; i--) {
        const isSelectParent = moveList.some(item => {
          return this.tableSource[i].parentIds.includes(item.key)
        })
        if (isSelectParent) {
          // 清除左侧树选中的项
          const index = this.selectedLeftKeys.indexOf(this.tableSource[i].key)
          if (index > -1) {
            this.selectedLeftKeys.splice(index, 1)
          }
          // 清除右侧列表的项
          this.tableSource.splice(i, 1)
        }
      }
    },
    // 获取当前节点的所有父节点
    getParentNodesByChild (childNode, key = 'key') {
      const parentNodes = []
      function recursionFind (data) {
        let isFind = false
        isFind = data.some((node) => {
          return node[key] === childNode[key]
        })
        if (!isFind) {
          for (const node of data) {
            if (node.children) {
              parentNodes.push(node)
              if (recursionFind(node.children)) {
                isFind = true
                break
              } else {
                parentNodes.pop()
              }
            }
          }
        }
        return isFind
      }
      recursionFind(this.unitUserTreeData)
      return parentNodes
    },
    onLeftMove () {
      let moveList = this.getTreeNodes(this.unitUserTreeData, this.checkedRightKeys)
      // 往左侧移动时，删除右侧表格中对应的项
      this.removeKeyByRight(this.tableSource)
      // 往左侧移动时，清除掉左侧已选择的项
      this.removeKeyByRight(this.selectedLeftKeys)
      for (const node of moveList) {
        this.setChildNodeDisabled(node.children, false)
      }
      this.checkedRightKeys = []
    },
    // 根据右侧的选择key删除对应数据列表中的项
    removeKeyByRight (list = []) {
      for (let i = list.length - 1; i >= 0; i--) {
        if (this.checkedRightKeys.includes(list[i].key || list[i])) {
          list.splice(i, 1)
        }
      }
    },
    onSelectTree (checkedLeftKeys, { checked, checkedNodes, node, event }) {
      if (checked) {
        this.checkedLeftKeys.push(node.dataRef.key)
        this.selectedLeftKeys.push(node.dataRef.key)
      } else {
        let index = this.checkedLeftKeys.findIndex(key => key === node.dataRef.key)
        if (index > -1) {
          this.checkedLeftKeys.splice(index, 1)
        }
        index = this.selectedLeftKeys.findIndex(key => key === node.dataRef.key)
        if (index > -1) {
          this.selectedLeftKeys.splice(index, 1)
        }
      }
      const childList = node.dataRef.children
      if (childList.length > 0) {
        this.setChildNodeDisabled(childList, checked)
      }
    },
    setChildNodeDisabled (childList = [], checked) {
      for (const node of childList) {
        if (checked) {
          this.childDisabledKeys.push(node.key)
        } else {
          const index = this.childDisabledKeys.findIndex(key => key === node.key)
          if (index > -1) {
            this.childDisabledKeys.splice(index, 1)
          }
        }
        if (node.children) {
          this.setChildNodeDisabled(node.children, checked)
        }
      }
    },
    onSelectChange (selectedRowKeys) {
      this.checkedRightKeys = selectedRowKeys
    },
    // 根据 leftDisableKeys 设置左侧树形菜单项禁用状态
    setTreeNodeDisable (treeData = []) {
      for (const node of treeData) {
        this.$set(node, 'disabled', this.leftDisableKeys.includes(node.key))
        if (node.children) {
          this.setTreeNodeDisable(node.children)
        }
      }
    },

    // 根据 checkedLeftKeys 从树形菜单中获取节点完整数据信息
    getTreeNodes (treeData = [], keys = []) {
      let list = []
      for (const node of treeData) {
        if (keys.includes(node.key)) {
          list.push(node)
        }
        if (node.children) {
          list = list.concat(this.getTreeNodes(node.children, keys))
        }
      }
      return list
    },
    getUnitTreeData (treeNode) {
      const param = { parentId: treeNode.dataRef.key }
      return new Promise((resolve) => {
        unituser(param).then((rep) => {
          if (rep.unitusertree.length > 0) {
            treeNode.dataRef.children = rep.unitusertree
            if (treeNode.dataRef.disabled || treeNode.checked) {
              this.setChildNodeDisabled(treeNode.dataRef.children, true)
            }
            this.unitUserTreeData = [...this.unitUserTreeData]
            this.setTreeNodeDisable(treeNode.dataRef.children)
            resolve()
          } else {
            resolve()
          }
        })
      })
    }
  }
}
</script>

<style lang="less" scoped>
.custom-transfer-wrap {
  display: flex;
  margin-top: 15px;
  .transfer-left,
  .transfer-right {
    flex: auto;
    position: relative;
    display: inline-block;
    width: 180px;
    height: 500px;
    vertical-align: middle;
    border: 1px solid #d9d9d9;
    border-radius: 4px;
    .header-wrap {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 15px 12px;
      border-bottom: 1px solid #e8e8e8;
    }
    .body-wrap {
      height: 430px;
      overflow: auto;
      padding: 12px;
    }
    ::v-deep.ant-table-placeholder {
      border: none;
    }
  }
  .transfer-operation {
    margin: 0 8px;
    align-self: center;
    .ant-btn {
      display: block;
      margin-bottom: 4px;
    }
  }
}
</style>